#light "off"
module Error = struct
    exception Exit of int
    type info = FI of string * int * int | UNKNOWN
    type 'a withinfo = {i: info; v: 'a}

    let dummyinfo = UNKNOWN
    let createInfo f l c = FI(f, l, c)
    let printInfo = function
        |FI(f,l,c) ->
            System.Console.Write( f + ":");
            System.Console.Write( l );
            System.Console.Write(".");
            System.Console.Write( c );
            System.Console.Write( ":" )
        |UNKNOWN ->
            System.Console.Write( "<Unknown file and line>:" )

    let errf f =
        System.Console.Clear( );
        f( );
        System.Console.WriteLine( );
        raise (Exit 1)

    let errfAt fi f =
        errf(fun()->
            printInfo fi;
            System.Console.Write( " ");
            f())

    let warning (s : string) =
        System.Console.Write( "Warning: ");
        System.Console.Write( s );
        System.Console.WriteLine( )

    let warningAt fi (s : string) =
        printInfo fi;
        System.Console.Write( " Warning: " );
        System.Console.Write( s );
        System.Console.WriteLine( )
end
module Pervasive = struct
    type info = Error.info
    let pr (str : string) = System.Console.Write( str )

    let rec prf filename (str : string) =
        match filename with
        |None ->
            pr str
        |Some filename ->
            match System.IO.File.Exists(filename) with
            |true -> 
                System.IO.File.Delete(filename);
                prf (Some filename) str
            |false ->
                let sw = System.IO.File.CreateText(filename) in
                sw.WriteLine( str );
                sw.Close( )

    let un statement = ignore(statement)

    let fvar_ctr  = ref 0
    let fresh_lcid ( ) =
        let str = System.Convert.ToString( !fvar_ctr ) in
        fvar_ctr := 1 + !fvar_ctr;
        "fv" ^ str

    let tvar_ctr  = ref 0
    let fresh_ucid ( ) =
        let str = System.Convert.ToString( !tvar_ctr ) in
        tvar_ctr := 1 + !tvar_ctr;
        "TV" ^ str
end

(****************************************************
* List Utils
*****************************************************)
module ListSpecial = struct
    let cartesianProduct combineFunc alist blist =
        let comb a = List.map (fun b -> combineFunc a b) blist in
        List.concat (List.map (fun a -> comb a) alist)
end
